package cn.com.headfree.workflow.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import cn.com.headfree.workflow.cache.WorkFlowCache;
import cn.com.headfree.workflow.dto.PersonData;
import cn.com.headfree.workflow.dto.WorkFlowConditionJSONData;
import cn.com.headfree.workflow.dto.WorkFlowDto;
import cn.com.headfree.workflow.dto.WorkFlowJSONData;
import cn.com.headfree.workflow.dto.WorkFlowJSONObject;
import cn.com.headfree.workflow.dto.WorkFlowLinesJSONData;
import cn.com.headfree.workflow.dto.WorkFlowNodeJSONObject;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

public class ParseWorkFlowDataUtil {
	private static ParseWorkFlowDataUtil util = new ParseWorkFlowDataUtil();

	private ParseWorkFlowDataUtil() {
	}

	public static synchronized ParseWorkFlowDataUtil getInstance() {
		if (util == null) {
			util = new ParseWorkFlowDataUtil();
		}
		return util;
	}

	/**
	 * @方法名：getFirstApprover
	 * @功能说明：获得流程中的第一个人任务节点
	 * @author fengya
	 * @date 2014-1-24 上午09:28:54
	 * @param workFlowJSONData
	 * @return
	 * @return WorkFlowDto
	 */
	public WorkFlowDto getFirstApprover(String flowId,String workFlowJSONData) {
		// 把JSON字符串转变成JAVA对象
		return this.getFirstApprover(this.getWorkFlowJSONObject(flowId, workFlowJSONData));
	}
	
	/**
	 * @description 得到工作流JSON对象信息
	 * @author fengya
	 * @date 2015-9-28 上午11:27:17
	 * @param flowId
	 * @param workFlowJSONData
	 * @return
	 * @return WorkFlowJSONObject
	 */
	public synchronized WorkFlowJSONObject getWorkFlowJSONObject(String flowId,String workFlowJSONData){
		// 把JSON字符串转变成JAVA对象
		WorkFlowJSONObject workFlowJSONObject = WorkFlowCache.getInstance().getWorkFlowJSONObject(flowId);
		if(workFlowJSONObject == null){
			workFlowJSONObject = this.getWorkFlowJSONObject(workFlowJSONData);
			WorkFlowCache.getInstance().putWorkFlowJsonData(flowId, workFlowJSONObject);
		}
		return workFlowJSONObject;
	}

	/**
	 * @方法名：getCurrentNode
	 * @功能说明：在给定的JSON字符串中，通过节点名称和下一个进入节点的条件，获得节点对象
	 * @author fengya
	 * @date 2014-1-24 上午09:29:56
	 * @param workFlowJSONData
	 *            ：工作流JSON字符串
	 * @param nodeName
	 *            ：当前节点ID
	 * @param conValue
	 *            ：进入下个节点的条件值
	 * @return
	 * @return WorkFlowDto
	 */
	public WorkFlowDto getCurrentNode(String flowId,String workFlowJSONData, String nodeName, String conValue) {
		return this.getCurrentNode(this.getWorkFlowJSONObject(flowId, workFlowJSONData), nodeName, conValue);
	}
	/**
	 * @description 根据json数据和节点名称获得该节点下的分支列表数据
	 * @author fengya
	 * @date 2015-9-11 下午04:13:36
	 * @param workFlowJSONData
	 * @param nodeName
	 * @return
	 * @return List<WorkFlowConditionJSONData>
	 */
	public List<WorkFlowConditionJSONData> getNextNodeCondition(String flowId,String workFlowJSONData, String nodeName) {
		WorkFlowJSONObject workFlowJSONObject = this.getWorkFlowJSONObject(flowId, workFlowJSONData);
		String nextNodeId = this.getNextNode(workFlowJSONObject, nodeName);
		if (nextNodeId != null) {
			WorkFlowNodeJSONObject workFlowNodeJSONObject = workFlowJSONObject.getNodes().get(nextNodeId);
			if (workFlowNodeJSONObject.getType().equals("join")) {
				return workFlowNodeJSONObject.getConditions();
			}
		}
		return new ArrayList<WorkFlowConditionJSONData>();
	}

	/**
	 * @方法名：getWorkFlowJSONObject
	 * @功能说明：把工作流JSON字符串转变成JAVA对象
	 * @author fengya
	 * @date 2014-1-24 上午09:32:04
	 * @param workFlowJSONData
	 * @return
	 * @return WorkFlowJSONObject
	 */
	@SuppressWarnings({ "unchecked", "deprecation" })
	public WorkFlowJSONObject getWorkFlowJSONObject(String workFlowJSONData) {
		WorkFlowJSONObject workFlowJSONObject = new WorkFlowJSONObject();
		JSONObject jsonObject = JSONObject.fromObject(workFlowJSONData);
		WorkFlowJSONData jsonData = (WorkFlowJSONData) JSONObject.toBean(jsonObject, WorkFlowJSONData.class);
		workFlowJSONObject.setMax(jsonData.getMax());
		Iterator<Entry<String, String>> linesIt = jsonData.getLines().entrySet().iterator();
		Iterator<Entry<String, String>> nodesIt = jsonData.getNodes().entrySet().iterator();
		Map<String, WorkFlowNodeJSONObject> nodes = new HashMap<String, WorkFlowNodeJSONObject>();
		Map<String, WorkFlowLinesJSONData> lines = new HashMap<String, WorkFlowLinesJSONData>();
		Entry<String, String> entry = null;
		WorkFlowLinesJSONData workFlowLinesJSONData = null;
		while (linesIt.hasNext()) {
			entry = linesIt.next();
			jsonObject = JSONObject.fromObject(entry.getValue());
			workFlowLinesJSONData = (WorkFlowLinesJSONData) JSONObject.toBean(jsonObject, WorkFlowLinesJSONData.class);
			lines.put(entry.getKey(), workFlowLinesJSONData);
		}
		workFlowJSONObject.setLines(lines);
		WorkFlowNodeJSONObject workFlowNodeJSONObject = null;
		JSONArray array = null;
		while (nodesIt.hasNext()) {
			entry = nodesIt.next();
			jsonObject = JSONObject.fromObject(entry.getValue());
			workFlowNodeJSONObject = new WorkFlowNodeJSONObject();
			workFlowNodeJSONObject.setHeight(jsonObject.getInt("height"));
			workFlowNodeJSONObject.setLeft(jsonObject.getInt("left"));
			workFlowNodeJSONObject.setName(jsonObject.getString("name"));
			workFlowNodeJSONObject.setTop(jsonObject.getInt("top"));
			workFlowNodeJSONObject.setType(jsonObject.getString("type"));
			workFlowNodeJSONObject.setCurrentNode(entry.getKey());
			if(jsonObject.get("approveLimit") != null){
				workFlowNodeJSONObject.setApproveLimit(jsonObject.getInt("approveLimit"));
			}
			if (workFlowNodeJSONObject.getType().equals("task")) {
				workFlowNodeJSONObject.setPersons(this.getPersonData(jsonObject.getString("approvers")));
				workFlowNodeJSONObject.setSelMethod(jsonObject.getString("selMethod"));
			} else if (workFlowNodeJSONObject.getType().equals("join")) {
				workFlowNodeJSONObject.setLines(jsonObject.getString("lines"));
				workFlowNodeJSONObject.setNextNode(jsonObject.getString("nextNode"));
//				workFlowNodeJSONObject.setPreNode(jsonObject.getString("preNode"));
				if (jsonObject.getString("conditions") != null) {
					array = JSONArray.fromObject(jsonObject.getString("conditions"));
					List<WorkFlowConditionJSONData> conditionData = JSONArray.toList(array, WorkFlowConditionJSONData.class);
					workFlowNodeJSONObject.setConditions(conditionData);
				}
			}
			workFlowNodeJSONObject.setWidth(jsonObject.getInt("width"));
			nodes.put(entry.getKey(), workFlowNodeJSONObject);
		}
		workFlowJSONObject.setNodes(nodes);
		return workFlowJSONObject;
	}

	@SuppressWarnings({ "unchecked", "deprecation" })
	private List<PersonData> getPersonData(String personJSON){
		JSONArray array = JSONArray.fromObject(personJSON);
		return JSONArray.toList(array, PersonData.class);
	}
	/**
	 * @方法名：getFirstApprover
	 * @功能说明：得到当前工作流中的第一个任务节点信息
	 * @author fengya
	 * @date 2014-1-24 上午09:32:38
	 * @param workFlowJSONObject
	 * @return
	 * @return WorkFlowDto
	 */
	private WorkFlowDto getFirstApprover(WorkFlowJSONObject workFlowJSONObject) {
		Iterator<Entry<String, WorkFlowLinesJSONData>> linesIt = workFlowJSONObject.getLines().entrySet().iterator();
		Entry<String, WorkFlowLinesJSONData> entry = null;
		String toNode = null;
		while (linesIt.hasNext()) {
			entry = linesIt.next();
			if (entry.getValue().getFrom().equals("start")) {
				toNode = entry.getValue().getTo();
				break;
			}
		}
		WorkFlowNodeJSONObject workFlowNodeJSONData = workFlowJSONObject.getNodes().get(toNode);
		WorkFlowDto dto = new WorkFlowDto();
		dto.setApprovers(workFlowNodeJSONData.getPersons());
		dto.setNodeId(toNode);
		dto.setNodeName(workFlowNodeJSONData.getName());
		dto.setApproveLimit(workFlowNodeJSONData.getApproveLimit());
//		dto.setNextNodeId(this.getNextTaskNode(workFlowJSONObject, toNode, null));
//		dto.setNextNode(workFlowJSONObject.getNodes().get(this.getNextTaskNode(workFlowJSONObject, toNode, null)));
		return dto;
	}
	/**
	 * @description 获得当前节点的封装对象
	 * @author fengya
	 * @date 2015-9-11 下午04:14:17
	 * @param workFlowJSONObject
	 * @param nodeName
	 * @param conValue
	 * @return
	 * @return WorkFlowDto
	 */
	private WorkFlowDto getCurrentNode(WorkFlowJSONObject workFlowJSONObject, String nodeName, String conValue) {
		WorkFlowNodeJSONObject currentNode = this.getNode(workFlowJSONObject, nodeName, conValue);
		WorkFlowDto dto = new WorkFlowDto();
		dto.setApprovers(currentNode.getPersons());
		dto.setNodeId(currentNode.getCurrentNode());
		dto.setNodeName(currentNode.getName());
		if(currentNode.getNextNode() == null){
			dto.setNextNodeId("end");
		} else{
			dto.setNextNodeId(currentNode.getNextNode());
			dto.setNextNode(this.getNextNode(workFlowJSONObject.getNodes().get(currentNode.getNextNode())));
		}
//		dto.setPreNode(workFlowJSONObject.getNodes().get(currentNode.getPreNode()));
//		dto.setPreNodeId(currentNode.getPreNode());
		dto.setSelMethod(currentNode.getSelMethod());
		return dto;
	}
	/**
	 * @description 获得当前节点的下个节点对象
	 * @author fengya
	 * @date 2015-9-11 下午04:14:36
	 * @param currentNode
	 * @return
	 * @return WorkFlowDto
	 */
	private WorkFlowDto getNextNode(WorkFlowNodeJSONObject currentNode) {
		WorkFlowDto dto = new WorkFlowDto();
		dto.setApprovers(currentNode.getPersons());
		dto.setNodeId(currentNode.getCurrentNode());
		dto.setNodeName(currentNode.getName());
		dto.setNextNodeId(currentNode.getNextNode());
		dto.setSelMethod(currentNode.getSelMethod());
		return dto;
	}
	/**
	 * @description 从JSON数据中，根据选择条件进行获得节点的封装对象
	 * @author fengya
	 * @date 2015-9-11 下午04:14:56
	 * @param workFlowJSONObject
	 * @param nodeId
	 * @param conValue
	 * @return
	 * @return WorkFlowNodeJSONObject
	 */
	private WorkFlowNodeJSONObject getNode(WorkFlowJSONObject workFlowJSONObject, String nodeId, String conValue) {
		WorkFlowNodeJSONObject currentNode = null;
		if (workFlowJSONObject.getNodes().containsKey(nodeId)) {
			currentNode = workFlowJSONObject.getNodes().get(nodeId);
//			String preNodeId = this.getPreNode(workFlowJSONObject, nodeId);
			String nextNodeId = this.getNextTaskNode(workFlowJSONObject, nodeId, conValue);
//			currentNode.setPreNode(preNodeId);
			currentNode.setNextNode(nextNodeId);
		}
		return currentNode;
	}
	/**
	 * @description 得到前一个节点的ID
	 * @author fengya
	 * @date 2015-9-11 下午04:15:39
	 * @param workFlowJSONObject
	 * @param nodeId
	 * @return
	 * @return String
	 */
//	private String getPreNode(WorkFlowJSONObject workFlowJSONObject, String nodeId) {
//		if (nodeId.equals("start")) {
//			return null;
//		}
//		Iterator<Entry<String, WorkFlowLinesJSONData>> linesIt = workFlowJSONObject.getLines().entrySet().iterator();
//		Entry<String, WorkFlowLinesJSONData> entry = null;
//		while (linesIt.hasNext()) {
//			entry = linesIt.next();
//			if (entry.getValue().getTo().equals(nodeId)) {
//				if (!entry.getValue().getType().equals("task")) {
//					return this.getPreNode(workFlowJSONObject, entry.getValue().getFrom());
//				} else {
//					return entry.getValue().getFrom();
//				}
//			}
//		}
//		return null;
//	}
	/**
	 * @description 得到下个任务节点
	 * @author fengya
	 * @date 2015-9-11 下午04:15:59
	 * @param workFlowJSONObject
	 * @param nodeId
	 * @param conditionValue
	 * @return
	 * @return String
	 */
	private String getNextTaskNode(WorkFlowJSONObject workFlowJSONObject, String nodeId, String conditionValue) {
		if (nodeId.equals("end")) {
			return null;
		}
		Iterator<Entry<String, WorkFlowLinesJSONData>> linesIt = workFlowJSONObject.getLines().entrySet().iterator();
		Entry<String, WorkFlowLinesJSONData> entry = null;
		WorkFlowNodeJSONObject workFlowNodeJSONData = null;
		WorkFlowConditionJSONData workFlowConditionJSONData = null;
		while (linesIt.hasNext()) {
			entry = linesIt.next();
			if (entry.getValue().getFrom().equals(nodeId)) {
				if (entry.getValue().getTo().equals("end")) {
					return null;
				}
				workFlowNodeJSONData = workFlowJSONObject.getNodes().get(entry.getValue().getTo());
				if (workFlowNodeJSONData.getType().equals("join")) {
					List<WorkFlowConditionJSONData> conList = workFlowNodeJSONData.getConditions();
					Iterator<WorkFlowConditionJSONData> conIt = conList.iterator();
					while (conIt.hasNext()) {
						workFlowConditionJSONData = conIt.next();
						if (workFlowConditionJSONData.getHandleResultValue().equals(conditionValue)) {
							return workFlowConditionJSONData.getToNode();
						}
					}
				} else {
					return entry.getValue().getTo();
				}
			}
		}
		return null;
	}
	/**
	 * @description 得到下个节点的ID，如果是结束节点，返回Null
	 * @author fengya
	 * @date 2015-9-11 下午04:16:14
	 * @param workFlowJSONObject
	 * @param nodeId
	 * @return
	 * @return String
	 */
	private String getNextNode(WorkFlowJSONObject workFlowJSONObject, String nodeId) {
		if (nodeId.equals("end")) {
			return null;
		}
		Iterator<Entry<String, WorkFlowLinesJSONData>> linesIt = workFlowJSONObject.getLines().entrySet().iterator();
		Entry<String, WorkFlowLinesJSONData> entry = null;
		while (linesIt.hasNext()) {
			entry = linesIt.next();
			if (entry.getValue().getFrom().equals(nodeId)) {
				if (entry.getValue().getTo().equals("end")) {
					return null;
				}
				return entry.getValue().getTo();
			}
		}
		return null;
	}
}
